/* 
Scenic Graphics Library
Copyright (C) 2007 Jouni Tulkki

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USApackage scenic;
*/

package scenic.jni;

import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.GraphicsEnvironment;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;

public class RenderCanvas extends Canvas {
	private static final long serialVersionUID = 1L;
	private static boolean libLoaded = false;
	
	static {
		loadLibrary();
	}
	
	public static void loadLibrary() {
		if(!libLoaded) {
			// we must PRE-LOAD jawt before any jawt-dependent dll
			JAWTLoader.loadAWTImpl();

			try
			{
				// now we can load the scenic jni
				System.loadLibrary("ScenicJNI");
				initLibrary();
				libLoaded = true;
			}

			catch (Throwable e)
			{
				System.out.println("Error: ScenicJNI library not loaded");
			}			
		}
	}
	
	int id = 0;
	private int width;
	private int height;
	
	private class CanvasHierarchyListener implements HierarchyListener {
		public void hierarchyChanged(HierarchyEvent e) {
			if((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0) {
				if(!isShowing())
					release();
			}
		}
	}
	
	public RenderCanvas()
	{
		super(XCanvas.findConfiguration(GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice()));
		addHierarchyListener(new CanvasHierarchyListener());
	}
	
	public void paint(Graphics g) {
		if(id == 0) {
			id = nativeCreate();
			width = getWidth();
			height = getHeight();
		}
		else if(width != getWidth() || height != getHeight()) {
			nativeReset(id);
			width = getWidth();
			height = getHeight();
		}
	}
	
	public void release() {
		if(id != 0) {
			nativeRelease(id);
			id = 0;
		}		
	}
	
	public void finalize() {
		release();
	}
	
	public void update(Graphics g) {
		paint(g);
	}
	
	private static native void initLibrary();
	private native int nativeCreate();
	private native void nativeReset(int id);
	private native void nativeRelease(int id);
	
	public int getContext() {
		return id;
	}
	
	public boolean getIsIntialized() {
		return id != 0;
	}
	
	public void addNotify() {
		super.addNotify();
		disableBackgroundErase();
	}
	
	private static boolean disableBackgroundEraseInitialized;
	private static Method  disableBackgroundEraseMethod;
	
	/*
	 * Workaround for a bug in J2SE 6.0 that causes flicker when canvas is resized.
	 * Taken from jogl.
	 */
	private void disableBackgroundErase() {
		if (!disableBackgroundEraseInitialized) {
			try {
				AccessController.doPrivileged(new PrivilegedAction<Object>() {
					public Object run() {
						try {
							disableBackgroundEraseMethod =
								getToolkit().getClass().getDeclaredMethod("disableBackgroundErase",
										new Class<?>[] { Canvas.class });
							disableBackgroundEraseMethod.setAccessible(true);
						} catch (Exception e) {
						}
						return null;
					}
				});
			} catch (Exception e) {
			}
			disableBackgroundEraseInitialized = true;
		}
		if (disableBackgroundEraseMethod != null) {
			try {
				disableBackgroundEraseMethod.invoke(getToolkit(), new Object[] { this });
			} catch (Exception e) {
				// FIXME: workaround for 6504460 (incorrect backport of 6333613 in 5.0u10)
				// throw new GLException(e);
			}
		}
	}
	
}
